package com.irdstudio.biz.rule.aop;

import com.irdstudio.biz.rule.common.constant.Constant.RULE_COLL_STATE;
import com.irdstudio.biz.rule.common.constant.Constant.RULE_COLL_TYPE;
import com.irdstudio.biz.rule.dao.SRuleCollInfoDao;
import com.irdstudio.biz.rule.dao.domain.BizRuleLog;
import com.irdstudio.biz.rule.dao.domain.BizRuleLogDetail;
import com.irdstudio.biz.rule.dao.domain.SRuleCollInfo;
import com.irdstudio.biz.rule.service.vo.SRuleCollInfoVO;
import com.irdstudio.sdk.ssm.vo.UserInfo;
import org.apache.commons.collections.CollectionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.test.util.ReflectionTestUtils;

import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.List;

/**
 * 规则业务逻辑aop
 * 控制审批大纲在当前系统只有一个启用
 * 非创建人不能修改创建人的数据
 */
@Aspect
@Component
public class BizRuleAspect {

    private static Logger log = LoggerFactory.getLogger(BizRuleAspect.class);

    @Autowired
    private SRuleCollInfoDao sRuleCollInfoDao;

    @Autowired
    private HttpSession currentSession;

    /**
     * 打切面到 SRuleCollInfoDao
     */
    @Pointcut("execution(public * com.irdstudio.biz.rule.dao.SRuleCollInfoDao.*(..))")
    private void constaintApprovalOnlyPointcut(){}

    @Before("constaintApprovalOnlyPointcut()")
    public void constaintApprovalOnly(JoinPoint jp){
        String methodName = jp.getSignature().getName();

        if (Arrays.asList("insertSRuleCollInfo", "updateByPk").contains(methodName)) {
            SRuleCollInfo sRuleCollInfo = (SRuleCollInfo) jp.getArgs()[0];
            if (!constaintApprovalOnly(sRuleCollInfo)) {
                throw new RuntimeException("审批大纲规则集只能有一条生效规则集");
            }
        }
    }


    /**
     * 约束只有一个启用的审批大纲
     * @param sRuleCollInfo
     * @return 只有一个，或者没有时，返回true
     */
    private boolean constaintApprovalOnly(SRuleCollInfo sRuleCollInfo) {
        if (sRuleCollInfo == null) {
            return true;
        }
        String collState = sRuleCollInfo.getRuleCollState();
        if (collState == null) {
            collState = RULE_COLL_STATE.INVALID.getCode();
        }
        // 更将新增的规则集为审批大纲时，检查是否有其它启用的审批大纲
        if (sRuleCollInfo.getRuleCollType() != null
                && sRuleCollInfo.getRuleCollType().equals(RULE_COLL_TYPE.Approval.getCode())
                && collState.equals(RULE_COLL_STATE.VALID.getCode())) {

            SRuleCollInfoVO param = new SRuleCollInfoVO();
            param.setRuleCollState(RULE_COLL_STATE.VALID.getCode());
            param.setRuleCollType(RULE_COLL_TYPE.Approval.getCode());
            List<SRuleCollInfo> approvalList = sRuleCollInfoDao.queryAllOwnerByPage(param);
            if (CollectionUtils.isNotEmpty(approvalList)) {
                if (approvalList.size() == 1) {
                    SRuleCollInfo info = approvalList.get(0);
                    return info.getRuleCollId().equals(sRuleCollInfo.getRuleCollId());
                } else {
                    return false;
                }
            } else {
                return true;
            }
        } else {
            return true;
        }
    }



    /**
     * 打切面到 Dao
     */
    @Pointcut("execution(public * com.irdstudio.biz.rule.dao..*.deleteByPk(..)) " +
            "|| execution(public * com.irdstudio.biz.rule.dao..*.updateByPk(..))")
    private void constaintDataModifyPointcut(){}

    @Before("constaintDataModifyPointcut()")
    public void constaintDataModify(JoinPoint jp){
        String methodName = jp.getSignature().getName();
        Object daoObj = jp.getArgs()[0];
        // 忽略日志domain
        if (daoObj instanceof BizRuleLog || daoObj instanceof BizRuleLogDetail) {
            return ;
        }
        UserInfo userInfo = (UserInfo) this.currentSession.getAttribute("userInfo");
        if (userInfo == null) {
            throw new RuntimeException("无法获取当前用户，不能修改删除数据");
        }
        log.debug("current user is {}", userInfo.getUserId());
        // 检查当前用户是否为该记录的创建人，不是本人，不能修删除数据
        String createUserId = (String) ReflectionTestUtils.invokeGetterMethod(daoObj, "createUser");
        if (createUserId == null) {
            // 创建人为空，不管控
            return;
        }
        if (!createUserId.equals(userInfo.getUserId())) {
            throw new RuntimeException("非创建人，不能修改删除数据");
        }
    }
}
